<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<!-- 
	Copyright (C) 2007, 2008, 2009, 2010, 2011. PARP Research Group.
	<http://perception.inf.um.es>
	University of Murcia, Spain.

	This file is part of the QVision library.

	QVision is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as
	published by the Free Software Foundation, version 3 of the License.

	QVision is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with QVision. If not, see <http://www.gnu.org/licenses/>.
-->

<html><head><meta http-equiv="content-Type" content="text/html;charset=UTF-8">
<title>QVision: Qt&#39;s Image, Video and Computer Vision Library</title>
<meta name="title" content="QVision" />
<meta name="dc.title" content="QVision" />
<meta name="url" content="http://perception.inf.um.es/QVision" />
<meta name="author" content="PARP Research Group - http://perception.inf.um.es" />
<meta name="revisit-after" content="30 DAYS"/>
<meta name="robots" content="index,follow"/>
<meta name="classification" content="*">
<meta name="rating" content="Safe For Kids">
<meta name="distribution" content="GLOBAL"/>
<meta name="description" content="Qt's Image, Video and Computer Vision Library"/>
<meta name="page-topic" content="Computer Vision research and prototype programming"/>
<meta name="geo.country" content="ES" />

<!--
Keywords:
By license:		open source, gnu, lgpl, gpl, free
By theme:		computer vision, image processing, robotics, programming, source, development
By usage:		library, toolkit, framework, prototype, application
By programming specs:	object oriented, c++, block programming, reusability, gui, graphical, parallel computing, high performance, GPU, prototyping
Interoperability with:	Qt, GSL, GNU Scientific library, OpenCV, CGAL, QWT, CUDA, mplayer, IPP, Intel Image Performance Primitives, blas, lapack
Functionallity:		image features, matrix algebra, projective geometry, mser, function minimization, function optimization, canny operator, harris operator, corner detection, performance evaluation, cpu usage, graphical interface
Main data-types:	matrix, vector, tensor, quaternion, image, polyline
Video sources:		webcam, camera, stream
Devices:		embedded, desktop computer, laptop, mini-laptop
Authors:		PARP research group. University of Murcia, Spain.
-->

<meta name="keywords" content="augmented reality, sfm, structure from motion, open source, gnu, lgpl, gpl, free, computer vision, image processing, robotics, programming, source, development, library, toolkit, framework, prototype, application, object oriented, c++, block programming, reusability, gui, graphical, parallel computing, high performance, GPU, prototyping, Qt, GSL, GNU Scientific library, OpenCV, CGAL, QWT, CUDA, mplayer, IPP, Intel Image Performance Primitives, blas, lapack, image features, matrix algebra, projective geometry, mser, function minimization, function optimization, canny operator, harris operator, corner detection, performance evaluation, cpu usage, graphical interface, matrix, vector, tensor, quaternion, image, polyline, webcam, camera, stream, embedded, desktop computer, laptop, mini-laptop, University of Murcia, Spain, PARP research group, vision por computador"/>
<meta http-equiv="keywords" content="augmented reality, sfm, structure from motion, open source, gnu, lgpl, gpl, free, computer vision, image processing, robotics, programming, source, development, library, toolkit, framework, prototype, application, object oriented, c++, block programming, reusability, gui, graphical, parallel computing, high performance, GPU, prototyping, Qt, GSL, GNU Scientific library, OpenCV, CGAL, QWT, CUDA, mplayer, IPP, Intel Image Performance Primitives, blas, lapack, image features, matrix algebra, projective geometry, mser, function minimization, function optimization, canny operator, harris operator, corner detection, performance evaluation, cpu usage, graphical interface, matrix, vector, tensor, quaternion, image, polyline, webcam, camera, stream, embedded, desktop computer, laptop, mini-laptop, University of Murcia, Spain, PARP research group, vision por computador"/>
<meta http-equiv="pragma" content="no-cache"/>
<meta http-equiv="title" content="QVision"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="tabs.css" rel="stylesheet" type="text/css" />
<link rel="shortcut icon" href="favicon.ico" />
</head><body>

<table width="100%"><tr>
	<td><a href="http://perception.inf.um.es/"><img src="parp.png" border="0" /> <big>PARP Research Group</big></a></td>
	<td align="right"><a href="http://www.um.es/"><big>Universidad de Murcia</big> <img src="um.png" border="0" /></a></td>
</tr></table>

<hr /><br />

<table width="95%" align="center"><tr><td>

<!-- Generated by Doxygen 1.6.3 -->
<script type="text/javascript"><!--
var searchBox = new SearchBox("searchBox", "search",false,'Search');
--></script>
<div class="navigation" id="top">
  <div class="tabs">
    <ul>
      <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
      <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
      <li><a href="modules.html"><span>Modules</span></a></li>
      <li><a href="annotated.html"><span>Classes</span></a></li>
      <li class="current"><a href="files.html"><span>Files</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
          <form id="FSearchBox" action="search.php" method="get">
            <img id="MSearchSelect" src="search/search.png" alt=""/>
            <input type="text" id="MSearchField" name="query" value="Search" size="20" accesskey="S" 
                   onfocus="searchBox.OnSearchFieldFocus(true)" 
                   onblur="searchBox.OnSearchFieldFocus(false)"/>
          </form>
        </div>
      </li>
    </ul>
  </div>
  <div class="tabs">
    <ul>
      <li><a href="files.html"><span>File&nbsp;List</span></a></li>
      <li><a href="globals.html"><span>File&nbsp;Members</span></a></li>
    </ul>
  </div>
<h1>src/qvmath/qvepipolar.cpp</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
<a name="l00002"></a>00002 <span class="comment"> *      Copyright (C) 2011, 2012. PARP Research Group.</span>
<a name="l00003"></a>00003 <span class="comment"> *      &lt;http://perception.inf.um.es&gt;</span>
<a name="l00004"></a>00004 <span class="comment"> *      University of Murcia, Spain.</span>
<a name="l00005"></a>00005 <span class="comment"> *</span>
<a name="l00006"></a>00006 <span class="comment"> *      This file is part of the QVision library.</span>
<a name="l00007"></a>00007 <span class="comment"> *</span>
<a name="l00008"></a>00008 <span class="comment"> *      QVision is free software: you can redistribute it and/or modify</span>
<a name="l00009"></a>00009 <span class="comment"> *      it under the terms of the GNU Lesser General Public License as</span>
<a name="l00010"></a>00010 <span class="comment"> *      published by the Free Software Foundation, version 3 of the License.</span>
<a name="l00011"></a>00011 <span class="comment"> *</span>
<a name="l00012"></a>00012 <span class="comment"> *      QVision is distributed in the hope that it will be useful,</span>
<a name="l00013"></a>00013 <span class="comment"> *      but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<a name="l00014"></a>00014 <span class="comment"> *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
<a name="l00015"></a>00015 <span class="comment"> *      GNU Lesser General Public License for more details.</span>
<a name="l00016"></a>00016 <span class="comment"> *</span>
<a name="l00017"></a>00017 <span class="comment"> *      You should have received a copy of the GNU Lesser General Public</span>
<a name="l00018"></a>00018 <span class="comment"> *      License along with QVision. If not, see &lt;http://www.gnu.org/licenses/&gt;.</span>
<a name="l00019"></a>00019 <span class="comment"> */</span>
<a name="l00020"></a>00020 
<a name="l00021"></a>00021 <span class="preprocessor">#include &lt;qvmath/qvepipolar.h&gt;</span>
<a name="l00022"></a>00022 <span class="preprocessor">#include &lt;math.h&gt;</span>
<a name="l00023"></a>00023 
<a name="l00024"></a>00024 <span class="comment">// Returns M = DLT matrix</span>
<a name="l00025"></a>00025 <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> getDLTMatrix(<span class="keyword">const</span> QVector&lt;QPointFMatching&gt; &amp;matchings)
<a name="l00026"></a>00026         {
<a name="l00027"></a>00027         <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> A(matchings.size(),9);
<a name="l00028"></a>00028         <span class="keywordtype">double</span> *aptr = A.<a class="code" href="classQVMatrix.html#a0c5b1e685d14d230c55cfcfb058e372a" title="Gets a reference of the data buffer of the matrix for read and write accesses.">getWriteData</a>();
<a name="l00029"></a>00029 
<a name="l00030"></a>00030         <span class="keywordflow">foreach</span>(<a class="code" href="group__qvmath.html#ga818fe0c689af956cd14431148c879718">QPointFMatching</a> matching,matchings)
<a name="l00031"></a>00031                 {
<a name="l00032"></a>00032                 <span class="keyword">const</span> QPointF   sourcePoint = matching.first,
<a name="l00033"></a>00033                                                 destPoint = matching.second;
<a name="l00034"></a>00034                 <span class="keyword">const</span> <span class="keywordtype">double</span>    x = sourcePoint.x(),
<a name="l00035"></a>00035                                                 y = sourcePoint.y(),
<a name="l00036"></a>00036                                                 x_p = destPoint.x(),
<a name="l00037"></a>00037                                                 y_p = destPoint.y();
<a name="l00038"></a>00038 
<a name="l00039"></a>00039                 <span class="comment">// Faster:</span>
<a name="l00040"></a>00040                 aptr[0] = x*x_p;
<a name="l00041"></a>00041                 aptr[1] = y*x_p;
<a name="l00042"></a>00042                 aptr[2] = x_p;
<a name="l00043"></a>00043                 aptr[3] = x*y_p;
<a name="l00044"></a>00044                 aptr[4] = y*y_p;
<a name="l00045"></a>00045                 aptr[5] = y_p;
<a name="l00046"></a>00046                 aptr[6] = x;
<a name="l00047"></a>00047                 aptr[7] = y;
<a name="l00048"></a>00048                 aptr[8] = 1.0;
<a name="l00049"></a>00049                 aptr += 9;
<a name="l00050"></a>00050                 }
<a name="l00051"></a>00051         <span class="keywordflow">return</span> A;
<a name="l00052"></a>00052         }
<a name="l00053"></a>00053 
<a name="l00054"></a>00054 <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> getSquaredDLTMatrix(<span class="keyword">const</span> QVector&lt;QPointFMatching&gt; &amp;matchings, <span class="keyword">const</span> QPointF &amp;m0c, <span class="keyword">const</span> QPointF &amp;m1c, <span class="keyword">const</span> <span class="keywordtype">double</span> &amp;scale0, <span class="keyword">const</span> <span class="keywordtype">double</span> &amp;scale1)
<a name="l00055"></a>00055     {
<a name="l00056"></a>00056         <span class="keywordtype">double</span> accum[36];
<a name="l00057"></a>00057         <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i = 0; i &lt; 36; i++)
<a name="l00058"></a>00058                 accum[i] = 0.0;
<a name="l00059"></a>00059 
<a name="l00060"></a>00060         <span class="keyword">const</span> <span class="keywordtype">double</span>    m0c_x = m0c.x(),        m0c_y = m0c.y(),
<a name="l00061"></a>00061                                         m1c_x = m1c.x(),        m1c_y = m1c.y();
<a name="l00062"></a>00062 
<a name="l00063"></a>00063         <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i = 0; i &lt; matchings.count(); i++)
<a name="l00064"></a>00064         {
<a name="l00065"></a>00065                 <span class="keyword">const</span> <a class="code" href="group__qvmath.html#ga818fe0c689af956cd14431148c879718">QPointFMatching</a> &amp;matching = matchings[i];
<a name="l00066"></a>00066         <span class="keyword">const</span> QPointF   &amp;sourcePoint = matching.first,
<a name="l00067"></a>00067                                                 &amp;destPoint = matching.second;
<a name="l00068"></a>00068 
<a name="l00069"></a>00069         <span class="keyword">const</span> <span class="keywordtype">double</span>    x = scale0 * (sourcePoint.x() - m0c_x),
<a name="l00070"></a>00070                                                 y = scale0 * (sourcePoint.y() - m0c_y),
<a name="l00071"></a>00071                                 xp = scale1 * (destPoint.x() - m1c_x),
<a name="l00072"></a>00072                                                 yp = scale1 * (destPoint.y() - m1c_y);
<a name="l00073"></a>00073 
<a name="l00074"></a>00074                 <span class="comment">/*</span>
<a name="l00075"></a>00075 <span class="comment">                # MAPLE CODE</span>
<a name="l00076"></a>00076 <span class="comment">                with(VectorCalculus):</span>
<a name="l00077"></a>00077 <span class="comment">                with(LinearAlgebra):</span>
<a name="l00078"></a>00078 <span class="comment"></span>
<a name="l00079"></a>00079 <span class="comment">                v:= Matrix([ [x xp], [y xp], [xp], [x yp], [y yp], [yp], [x], [y], [1]  ] );</span>
<a name="l00080"></a>00080 <span class="comment">                M := v.Transpose(v);</span>
<a name="l00081"></a>00081 <span class="comment">                V := Vector([M[1,1], M[1,2], M[1,3], M[1,4], M[1,5], M[1,6], M[1,7], M[1,8], M[1,9], M[2,2], M[2,3], M[2,5],</span>
<a name="l00082"></a>00082 <span class="comment">                        M[2,6], M[2,8], M[2,9], M[3,3], M[3,6], M[3,9], M[4,4], M[4,5], M[4,6], M[4,7], M[4,8], M[4,9], M[5,5],</span>
<a name="l00083"></a>00083 <span class="comment">                        M[5,6], M[5,8], M[5,9], M[6,6], M[6,9], M[7,7], M[7,8], M[7,9], M[8,8], M[8,9], M[9,9] ]);</span>
<a name="l00084"></a>00084 <span class="comment"></span>
<a name="l00085"></a>00085 <span class="comment">                CodeGeneration[C](V, optimize = true);</span>
<a name="l00086"></a>00086 <span class="comment">                */</span>
<a name="l00087"></a>00087                 <span class="keyword">const</span> <span class="keywordtype">double</span>    t1 = x * x,
<a name="l00088"></a>00088                                                 t2 = xp * xp,
<a name="l00089"></a>00089                                                 t4 = x * t2,
<a name="l00090"></a>00090                                                 t6 = t1 * xp,
<a name="l00091"></a>00091                                                 t8 = x * xp,
<a name="l00092"></a>00092                                                 t9 = y * yp,
<a name="l00093"></a>00093                                                 t13 = y * y,
<a name="l00094"></a>00094                                                 t16 = t13 * xp,
<a name="l00095"></a>00095                                                 t18 = y * xp,
<a name="l00096"></a>00096                                                 t21 = yp * yp,
<a name="l00097"></a>00097                                                 t23 = x * t21,
<a name="l00098"></a>00098                                                 t26 = x * yp;
<a name="l00099"></a>00099 
<a name="l00100"></a>00100                 accum[0] += t1 * t2;
<a name="l00101"></a>00101                 accum[1] += t4 * y;
<a name="l00102"></a>00102                 accum[2] += t4;
<a name="l00103"></a>00103                 accum[3] += t6 * yp;
<a name="l00104"></a>00104                 accum[4] += t8 * t9;
<a name="l00105"></a>00105                 accum[5] += t8 * yp;
<a name="l00106"></a>00106                 accum[6] += t6;
<a name="l00107"></a>00107                 accum[7] += t8 * y;
<a name="l00108"></a>00108                 accum[8] += t8;
<a name="l00109"></a>00109                 accum[9] += t13 * t2;
<a name="l00110"></a>00110                 accum[10] += y * t2;
<a name="l00111"></a>00111                 accum[11] += t16 * yp;
<a name="l00112"></a>00112                 accum[12] += t18 * yp;
<a name="l00113"></a>00113                 accum[13] += t16;
<a name="l00114"></a>00114                 accum[14] += t18;
<a name="l00115"></a>00115                 accum[15] += t2;
<a name="l00116"></a>00116                 accum[16] += xp * yp;
<a name="l00117"></a>00117                 accum[17] += xp;
<a name="l00118"></a>00118                 accum[18] += t1 * t21;
<a name="l00119"></a>00119                 accum[19] += t23 * y;
<a name="l00120"></a>00120                 accum[20] += t23;
<a name="l00121"></a>00121                 accum[21] += t1 * yp;
<a name="l00122"></a>00122                 accum[22] += t26 * y;
<a name="l00123"></a>00123                 accum[23] += t26;
<a name="l00124"></a>00124                 accum[24] += t13 * t21;
<a name="l00125"></a>00125                 accum[25] += y * t21;
<a name="l00126"></a>00126                 accum[26] += t13 * yp;
<a name="l00127"></a>00127                 accum[27] += t9;
<a name="l00128"></a>00128                 accum[28] += t21;
<a name="l00129"></a>00129                 accum[29] += yp;
<a name="l00130"></a>00130                 accum[30] += t1;
<a name="l00131"></a>00131                 accum[31] += x * y;
<a name="l00132"></a>00132                 accum[32] += x;
<a name="l00133"></a>00133                 accum[33] += t13;
<a name="l00134"></a>00134                 accum[34] += y;
<a name="l00135"></a>00135                 accum[35] += 1;
<a name="l00136"></a>00136         }
<a name="l00137"></a>00137 
<a name="l00138"></a>00138         <span class="keywordflow">return</span> <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a>(9,9, (<span class="keywordtype">double</span>[9*9])      {
<a name="l00139"></a>00139                                                                                 accum[0], accum[1], accum[2], accum[3], accum[4], accum[5], accum[6], accum[7], accum[8],
<a name="l00140"></a>00140                                                                                 accum[1], accum[9], accum[10], accum[4], accum[11], accum[12], accum[7], accum[13], accum[14],
<a name="l00141"></a>00141                                                                                 accum[2], accum[10], accum[15], accum[5], accum[12], accum[16], accum[8], accum[14], accum[17],
<a name="l00142"></a>00142                                                                                 accum[3], accum[4], accum[5], accum[18], accum[19], accum[20], accum[21], accum[22], accum[23],
<a name="l00143"></a>00143                                                                                 accum[4], accum[11], accum[12], accum[19], accum[24], accum[25], accum[22], accum[26], accum[27],
<a name="l00144"></a>00144                                                                                 accum[5], accum[12], accum[16], accum[20], accum[25], accum[28], accum[23], accum[27], accum[29],
<a name="l00145"></a>00145                                                                                 accum[6], accum[7], accum[8], accum[21], accum[22], accum[23], accum[30], accum[31], accum[32],
<a name="l00146"></a>00146                                                                                 accum[7], accum[13], accum[14], accum[22], accum[26], accum[27], accum[31], accum[33], accum[34],
<a name="l00147"></a>00147                                                                                 accum[8], accum[14], accum[17], accum[23], accum[27], accum[29], accum[32], accum[34], accum[35]
<a name="l00148"></a>00148                                                                                 }
<a name="l00149"></a>00149                                         );
<a name="l00150"></a>00150         }
<a name="l00151"></a>00151 
<a name="l00152"></a>00152 <span class="keywordtype">void</span> normalizeMatchingsForEpipolarestimation(<span class="keyword">const</span> QVector&lt;QPointFMatching&gt; &amp;matchings, QPointF &amp;m0c, QPointF &amp;m1c, <span class="keywordtype">double</span> &amp;scale0, <span class="keywordtype">double</span> &amp;scale1, <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> &amp;Q1, <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> &amp;Q2)
<a name="l00153"></a>00153         {
<a name="l00154"></a>00154     <span class="comment">// Compute centers and average distances for each of the two point sets</span>
<a name="l00155"></a>00155         m0c.rx() = 0.0; m0c.ry() = 0.0;
<a name="l00156"></a>00156         m1c.rx() = 0.0; m1c.ry() = 0.0;
<a name="l00157"></a>00157 
<a name="l00158"></a>00158     <span class="keywordflow">foreach</span>(<a class="code" href="group__qvmath.html#ga818fe0c689af956cd14431148c879718">QPointFMatching</a> matching, matchings)
<a name="l00159"></a>00159         {
<a name="l00160"></a>00160         m0c += matching.first;
<a name="l00161"></a>00161         m1c += matching.second;
<a name="l00162"></a>00162         }
<a name="l00163"></a>00163 
<a name="l00164"></a>00164     <span class="keyword">const</span> <span class="keywordtype">int</span> count = matchings.count();
<a name="l00165"></a>00165     m0c /= count;
<a name="l00166"></a>00166     m1c /= count;
<a name="l00167"></a>00167 
<a name="l00168"></a>00168     scale0 = 0.0;
<a name="l00169"></a>00169         scale1 = 0.0;
<a name="l00170"></a>00170     <span class="keywordflow">foreach</span>(<a class="code" href="group__qvmath.html#ga818fe0c689af956cd14431148c879718">QPointFMatching</a> matching, matchings)
<a name="l00171"></a>00171         {
<a name="l00172"></a>00172         scale0 += norm2(matching.first - m0c);
<a name="l00173"></a>00173         scale1 += norm2(matching.second - m1c);
<a name="l00174"></a>00174         }
<a name="l00175"></a>00175 
<a name="l00176"></a>00176     scale0 = count * sqrt(2.) /scale0;
<a name="l00177"></a>00177     scale1 = count * sqrt(2.) /scale1;
<a name="l00178"></a>00178 
<a name="l00179"></a>00179     <span class="comment">// Re-compose F truncating the third singular value, and correcting the whitening of the point correspondences</span>
<a name="l00180"></a>00180     Q1 = <a class="code" href="classQVMatrix.html#a953207e797ad5c2f8477d3507dbcf86b" title="Creates an intrinsic camera calibration matrix.">QVMatrix::cameraCalibrationMatrix</a>(scale0, 1.0, -scale0*m0c.x(), -scale0*m0c.y()),
<a name="l00181"></a>00181         Q2 = <a class="code" href="classQVMatrix.html#a953207e797ad5c2f8477d3507dbcf86b" title="Creates an intrinsic camera calibration matrix.">QVMatrix::cameraCalibrationMatrix</a>(scale1, 1.0, -scale1*m1c.x(), -scale1*m1c.y());
<a name="l00182"></a>00182         }
<a name="l00183"></a>00183 
<a name="l00184"></a>00184 <span class="keywordtype">bool</span> solveForFundamentalMatrix(<span class="keyword">const</span> <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> &amp;omega, <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> &amp;F, <span class="keyword">const</span> <a class="code" href="group__qvmatrixalgebra.html#gad753ba41cd08df7e8d4173d8c2ac2575" title="Available methods for Singular Value Decomposition (SVD).">TQVSVD_Method</a> svdMethod = DEFAULT_TQVSVD_METHOD)
<a name="l00185"></a>00185         {
<a name="l00186"></a>00186     <a class="code" href="classQVVector.html" title="Implementation of numerical vectors.">QVVector</a> x;
<a name="l00187"></a>00187     <a class="code" href="group__qvmatrixalgebra.html#gabcefb2cb61ed46e61130f4892308fee4" title="Solves an homogeneous linear system of equations.">solveHomogeneous</a>(omega, x, svdMethod);
<a name="l00188"></a>00188         <span class="keyword">const</span> <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> preF = <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a>(3,3, x);
<a name="l00189"></a>00189 
<a name="l00190"></a>00190         <span class="comment">// Decompose linear F with SVD.</span>
<a name="l00191"></a>00191         <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> U, V;
<a name="l00192"></a>00192         <a class="code" href="classQVVector.html" title="Implementation of numerical vectors.">QVVector</a> s;
<a name="l00193"></a>00193         <a class="code" href="group__qvmatrixalgebra.html#gabe654b66e21aa3d27131c5f65fcc9dfb" title="Obtains the Singular Value Decomposition (SVD) of a rectangular  matrix M.">singularValueDecomposition</a>(preF, U, s, V, svdMethod);
<a name="l00194"></a>00194 
<a name="l00195"></a>00195         <span class="keywordtype">double</span> *dataU = U.<a class="code" href="classQVMatrix.html#a0c5b1e685d14d230c55cfcfb058e372a" title="Gets a reference of the data buffer of the matrix for read and write accesses.">getWriteData</a>();
<a name="l00196"></a>00196         <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i = 0; i &lt; 3; i++)
<a name="l00197"></a>00197                 {
<a name="l00198"></a>00198                 dataU[3*i+0] *= s[0];
<a name="l00199"></a>00199                 dataU[3*i+1] *= s[1];
<a name="l00200"></a>00200                 dataU[3*i+2] = 0.0;
<a name="l00201"></a>00201                 }
<a name="l00202"></a>00202 
<a name="l00203"></a>00203         F = U.<a class="code" href="classQVMatrix.html#a5470e61c2827d5485596c3901690154c" title="Matrix-matrix product.">dotProduct</a>(V, <span class="keyword">false</span>, <span class="keyword">true</span>);
<a name="l00204"></a>00204 
<a name="l00205"></a>00205         <span class="keywordflow">return</span> (F.<a class="code" href="classQVMatrix.html#a387750529622104faba8047cb0efa62a" title="Gets the norm2 for matrix.">norm2</a>() &gt; MIN_FUNDAMENTAL_MATRIX_NORM);
<a name="l00206"></a>00206         }
<a name="l00207"></a>00207 
<a name="l00208"></a><a class="code" href="group__qvprojectivegeometry.html#ga721c81d3a9e9c7c2e09f5867241c7021">00208</a> <span class="keywordtype">bool</span> <a class="code" href="group__qvprojectivegeometry.html#ga721c81d3a9e9c7c2e09f5867241c7021" title="Obtains the fundamental matrix between two images using the 8-point algorithm.">computeFundamentalMatrix</a>(<span class="keyword">const</span> QVector&lt;QPointFMatching&gt; &amp;matchings, <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> &amp;F, <span class="keyword">const</span> <a class="code" href="group__qvmatrixalgebra.html#gad753ba41cd08df7e8d4173d8c2ac2575" title="Available methods for Singular Value Decomposition (SVD).">TQVSVD_Method</a> svdMethod)
<a name="l00209"></a>00209     {
<a name="l00210"></a>00210     <span class="keywordflow">if</span> (matchings.count() &lt; 8)
<a name="l00211"></a>00211         <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00212"></a>00212 
<a name="l00213"></a>00213         QPointF m0c, m1c;
<a name="l00214"></a>00214         <span class="keywordtype">double</span> scale0, scale1;
<a name="l00215"></a>00215         <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> Q1, Q2, preF;
<a name="l00216"></a>00216 
<a name="l00217"></a>00217         normalizeMatchingsForEpipolarestimation(matchings, m0c, m1c, scale0, scale1, Q1, Q2);
<a name="l00218"></a>00218 
<a name="l00219"></a>00219         <span class="comment">// Coefficient matrix.</span>
<a name="l00220"></a>00220         <span class="keyword">const</span> <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> omega = getSquaredDLTMatrix(matchings, m0c, m1c, scale0, scale1);
<a name="l00221"></a>00221 
<a name="l00222"></a>00222         <span class="keywordflow">if</span> (not solveForFundamentalMatrix(omega, preF, svdMethod))
<a name="l00223"></a>00223                 <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00224"></a>00224 
<a name="l00225"></a>00225         F = Q2.<a class="code" href="classQVMatrix.html#a2f87710c9d8ae4b07b03605daea3782e" title="Change the order of the indexes in the matrix.">transpose</a>() * preF * Q1;
<a name="l00226"></a>00226 
<a name="l00227"></a>00227     <span class="comment">// Todo: Some functions will not work properly if values are not cast to float. ¿Porqué?</span>
<a name="l00228"></a>00228     <span class="keywordflow">for</span>(<span class="keywordtype">int</span> j = 0; j &lt; 3; j++ )
<a name="l00229"></a>00229         <span class="keywordflow">for</span>(<span class="keywordtype">int</span> k = 0; k &lt; 3; k++ )
<a name="l00230"></a>00230             F(j,k) = float(F(j,k));
<a name="l00231"></a>00231 
<a name="l00232"></a>00232         <span class="keywordflow">return</span> <span class="keyword">true</span>;
<a name="l00233"></a>00233     }
<a name="l00234"></a>00234 
<a name="l00235"></a>00235 <a class="code" href="classQVVector.html" title="Implementation of numerical vectors.">QVVector</a> symmetricEpipolarDistance2(<span class="keyword">const</span> <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> &amp;F, <span class="keyword">const</span> QVector&lt;QPointFMatching&gt; &amp;matchings)
<a name="l00236"></a>00236         {
<a name="l00237"></a>00237         <span class="comment">//const double *f = F.getReadData();</span>
<a name="l00238"></a>00238 
<a name="l00239"></a>00239         <a class="code" href="classQVVector.html" title="Implementation of numerical vectors.">QVVector</a> result(matchings.count());
<a name="l00240"></a>00240         <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i = 0; i &lt; matchings.count(); i++)
<a name="l00241"></a>00241                 {
<a name="l00242"></a>00242                 <span class="keyword">const</span> QPointF   &amp;p1 = matchings[i].first,
<a name="l00243"></a>00243                                                 &amp;p2 = matchings[i].second;
<a name="l00244"></a>00244                 <span class="keyword">const</span> <a class="code" href="classQVVector.html" title="Implementation of numerical vectors.">QVVector</a>  l1 = F*<a class="code" href="classQV3DPointF.html" title="3D point representation">QV3DPointF</a>(p1.x(), p1.y(), 1.0),
<a name="l00245"></a>00245                                                 l2 = <a class="code" href="classQV3DPointF.html" title="3D point representation">QV3DPointF</a>(p2.x(), p2.y(), 1.0)*F;
<a name="l00246"></a>00246                 <span class="keyword">const</span> <span class="keywordtype">double</span>    distance =      <a class="code" href="group__qvmath.html#gaeb39222b657a43c07ce908b9813a8e6b" title="Obtains the geometric distance between a point and a line in the 2D plane.">qvPointLineDistance</a>(l1, p2) + <a class="code" href="group__qvmath.html#gaeb39222b657a43c07ce908b9813a8e6b" title="Obtains the geometric distance between a point and a line in the 2D plane.">qvPointLineDistance</a>(l2, p1);
<a name="l00247"></a>00247 
<a name="l00248"></a>00248                 result[i] = distance;
<a name="l00249"></a>00249                 }
<a name="l00250"></a>00250         <span class="keywordflow">return</span> result;
<a name="l00251"></a>00251         }
<a name="l00252"></a>00252 
<a name="l00253"></a><a class="code" href="group__qvprojectivegeometry.html#ga86b3bbbca7ae731894f90bfd9ebb3a3a">00253</a> <span class="keywordtype">double</span> <a class="code" href="group__qvprojectivegeometry.html#ga86b3bbbca7ae731894f90bfd9ebb3a3a" title="Evaluate symmetric epipolar error for a fundamental matrix defined between two images...">symmetricEpipolarDistance</a>(<span class="keyword">const</span> <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> &amp;F, <span class="keyword">const</span> <a class="code" href="group__qvmath.html#ga818fe0c689af956cd14431148c879718">QPointFMatching</a> &amp;matching)
<a name="l00254"></a>00254         {
<a name="l00255"></a>00255         <span class="keyword">const</span> <span class="keywordtype">double</span> *f = F.<a class="code" href="classQVMatrix.html#a50de15cc657c8a1d9fcc749161192a64" title="Gets a read-only reference to the data buffer of the matrix.">getReadData</a>();
<a name="l00256"></a>00256 
<a name="l00257"></a>00257         <span class="keyword">const</span> QPointF   &amp;p1 = matching.first,
<a name="l00258"></a>00258                                         &amp;p2 = matching.second;
<a name="l00259"></a>00259         <span class="keyword">const</span> <span class="keywordtype">double</span>    p1x = p1.x(), p1y = p1.y(),
<a name="l00260"></a>00260                                         p2x = p2.x(), p2y = p2.y();
<a name="l00261"></a>00261 
<a name="l00262"></a>00262         <span class="comment">/*</span>
<a name="l00263"></a>00263 <span class="comment">        # Maple code:</span>
<a name="l00264"></a>00264 <span class="comment">        with(VectorCalculus):</span>
<a name="l00265"></a>00265 <span class="comment">        with(LinearAlgebra):</span>
<a name="l00266"></a>00266 <span class="comment"></span>
<a name="l00267"></a>00267 <span class="comment">        # Input</span>
<a name="l00268"></a>00268 <span class="comment">        f := vector(9):</span>
<a name="l00269"></a>00269 <span class="comment"></span>
<a name="l00270"></a>00270 <span class="comment">        # F matrix</span>
<a name="l00271"></a>00271 <span class="comment">        P1 := Vector([p1x, p1y, 1]);</span>
<a name="l00272"></a>00272 <span class="comment">        P2 := Vector([p2x, p2y, 1]);</span>
<a name="l00273"></a>00273 <span class="comment">        F := Matrix([ [f[1], f[2], f[3]], [f[4], f[5], f[6]], [f[7], f[8], f[9]]]);</span>
<a name="l00274"></a>00274 <span class="comment"></span>
<a name="l00275"></a>00275 <span class="comment">        l1 := F.P1:</span>
<a name="l00276"></a>00276 <span class="comment">        l2 := Transpose(P2).F:</span>
<a name="l00277"></a>00277 <span class="comment"></span>
<a name="l00278"></a>00278 <span class="comment">        n1 := l1[1]*p2x + l1[2]*p2y + l1[3]:</span>
<a name="l00279"></a>00279 <span class="comment">        d1 := l1[1]*l1[1] + l1[2]*l1[2]:</span>
<a name="l00280"></a>00280 <span class="comment">        n2 := l2[1]*p1x + l2[2]*p1y + l2[3]:</span>
<a name="l00281"></a>00281 <span class="comment">        d2 := l2[1]*l2[1] + l2[2]*l2[2]:</span>
<a name="l00282"></a>00282 <span class="comment"></span>
<a name="l00283"></a>00283 <span class="comment">        CodeGeneration[C](Vector([n1, d1, n2, d2]), optimize = true);</span>
<a name="l00284"></a>00284 <span class="comment">        */</span>
<a name="l00285"></a>00285         <span class="keyword">const</span> <span class="keywordtype">double</span>    t3 = f[0] * p1x + f[1] * p1y + f[2],
<a name="l00286"></a>00286                                         t7 = f[3] * p1x + f[4] * p1y + f[5],
<a name="l00287"></a>00287                                         t12 = t3 * t3,
<a name="l00288"></a>00288                                         t13 = t7 * t7,
<a name="l00289"></a>00289                                         t17 = p2x * f[0] + p2y * f[3] + f[6],
<a name="l00290"></a>00290                                         t21 = p2x * f[1] + p2y * f[4] + f[7],
<a name="l00291"></a>00291                                         t26 = t17 * t17,
<a name="l00292"></a>00292                                         t27 = t21 * t21,
<a name="l00293"></a>00293                                         cg0 = t3 * p2x + t7 * p2y + f[6] * p1x + f[7] * p1y + f[8],
<a name="l00294"></a>00294                                         cg1 = t12 + t13,
<a name="l00295"></a>00295                                         cg2 = t17 * p1x + t21 * p1y + p2x * f[2] + p2y * f[5] + f[8],
<a name="l00296"></a>00296                                         cg3 = t26 + t27;
<a name="l00297"></a>00297 
<a name="l00298"></a>00298         <span class="keywordflow">return</span> ABS(cg0)/sqrt(cg1) + ABS(cg2)/sqrt(cg3);
<a name="l00299"></a>00299         }
<a name="l00300"></a>00300 
<a name="l00301"></a>00301 <span class="comment">// 10-fold speed up compared to symmetricEpipolarDistance2</span>
<a name="l00302"></a><a class="code" href="group__qvprojectivegeometry.html#gae93905c2b6cca18996c889210cbb6874">00302</a> <a class="code" href="classQVVector.html" title="Implementation of numerical vectors.">QVVector</a> <a class="code" href="group__qvprojectivegeometry.html#ga86b3bbbca7ae731894f90bfd9ebb3a3a" title="Evaluate symmetric epipolar error for a fundamental matrix defined between two images...">symmetricEpipolarDistance</a>(<span class="keyword">const</span> <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> &amp;F, <span class="keyword">const</span> QVector&lt;QPointFMatching&gt; &amp;matchings)
<a name="l00303"></a>00303         {
<a name="l00304"></a>00304         <span class="keyword">const</span> <span class="keywordtype">double</span> *f = F.<a class="code" href="classQVMatrix.html#a50de15cc657c8a1d9fcc749161192a64" title="Gets a read-only reference to the data buffer of the matrix.">getReadData</a>();
<a name="l00305"></a>00305 
<a name="l00306"></a>00306         <a class="code" href="classQVVector.html" title="Implementation of numerical vectors.">QVVector</a> result(matchings.count());
<a name="l00307"></a>00307         <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i = 0; i &lt; matchings.count(); i++)
<a name="l00308"></a>00308                 {
<a name="l00309"></a>00309                 <span class="keyword">const</span> QPointF   &amp;p1 = matchings[i].first,
<a name="l00310"></a>00310                                                 &amp;p2 = matchings[i].second;
<a name="l00311"></a>00311                 <span class="keyword">const</span> <span class="keywordtype">double</span>    p1x = p1.x(), p1y = p1.y(),
<a name="l00312"></a>00312                                                 p2x = p2.x(), p2y = p2.y();
<a name="l00313"></a>00313 
<a name="l00314"></a>00314                 <span class="comment">/*</span>
<a name="l00315"></a>00315 <span class="comment">                # Maple code:</span>
<a name="l00316"></a>00316 <span class="comment">                with(VectorCalculus):</span>
<a name="l00317"></a>00317 <span class="comment">                with(LinearAlgebra):</span>
<a name="l00318"></a>00318 <span class="comment"></span>
<a name="l00319"></a>00319 <span class="comment">                # Input</span>
<a name="l00320"></a>00320 <span class="comment">                f := vector(9):</span>
<a name="l00321"></a>00321 <span class="comment"></span>
<a name="l00322"></a>00322 <span class="comment">                # F matrix</span>
<a name="l00323"></a>00323 <span class="comment">                P1 := Vector([p1x, p1y, 1]);</span>
<a name="l00324"></a>00324 <span class="comment">                P2 := Vector([p2x, p2y, 1]);</span>
<a name="l00325"></a>00325 <span class="comment">                F := Matrix([ [f[1], f[2], f[3]], [f[4], f[5], f[6]], [f[7], f[8], f[9]]]);</span>
<a name="l00326"></a>00326 <span class="comment"></span>
<a name="l00327"></a>00327 <span class="comment">                l1 := F.P1:</span>
<a name="l00328"></a>00328 <span class="comment">                l2 := Transpose(P2).F:</span>
<a name="l00329"></a>00329 <span class="comment"></span>
<a name="l00330"></a>00330 <span class="comment">                n1 := l1[1]*p2x + l1[2]*p2y + l1[3]:</span>
<a name="l00331"></a>00331 <span class="comment">                d1 := l1[1]*l1[1] + l1[2]*l1[2]:</span>
<a name="l00332"></a>00332 <span class="comment">                n2 := l2[1]*p1x + l2[2]*p1y + l2[3]:</span>
<a name="l00333"></a>00333 <span class="comment">                d2 := l2[1]*l2[1] + l2[2]*l2[2]:</span>
<a name="l00334"></a>00334 <span class="comment"></span>
<a name="l00335"></a>00335 <span class="comment">                CodeGeneration[C](Vector([n1, d1, n2, d2]), optimize = true);</span>
<a name="l00336"></a>00336 <span class="comment">                */</span>
<a name="l00337"></a>00337                 <span class="keyword">const</span> <span class="keywordtype">double</span>    t3 = f[0] * p1x + f[1] * p1y + f[2],
<a name="l00338"></a>00338                                                 t7 = f[3] * p1x + f[4] * p1y + f[5],
<a name="l00339"></a>00339                                                 t12 = t3 * t3,
<a name="l00340"></a>00340                                                 t13 = t7 * t7,
<a name="l00341"></a>00341                                                 t17 = p2x * f[0] + p2y * f[3] + f[6],
<a name="l00342"></a>00342                                                 t21 = p2x * f[1] + p2y * f[4] + f[7],
<a name="l00343"></a>00343                                                 t26 = t17 * t17,
<a name="l00344"></a>00344                                                 t27 = t21 * t21,
<a name="l00345"></a>00345                                                 cg0 = t3 * p2x + t7 * p2y + f[6] * p1x + f[7] * p1y + f[8],
<a name="l00346"></a>00346                                                 cg1 = t12 + t13,
<a name="l00347"></a>00347                                                 cg2 = t17 * p1x + t21 * p1y + p2x * f[2] + p2y * f[5] + f[8],
<a name="l00348"></a>00348                                                 cg3 = t26 + t27;
<a name="l00349"></a>00349 
<a name="l00350"></a>00350                 result[i] = ABS(cg0)/sqrt(cg1) + ABS(cg2)/sqrt(cg3);
<a name="l00351"></a>00351                 }
<a name="l00352"></a>00352 
<a name="l00353"></a>00353 <span class="preprocessor">        #ifdef DEBUG</span>
<a name="l00354"></a>00354 <span class="preprocessor"></span>        <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i = 0; i &lt; result.count(); i++)
<a name="l00355"></a>00355                 {
<a name="l00356"></a>00356                 <span class="keyword">const</span> <span class="keywordtype">double</span> distance = ABS(result[i] - <a class="code" href="group__qvprojectivegeometry.html#ga86b3bbbca7ae731894f90bfd9ebb3a3a" title="Evaluate symmetric epipolar error for a fundamental matrix defined between two images...">symmetricEpipolarDistance</a>(F, matchings[i])) / (ABS(result[i]) + ABS(<a class="code" href="group__qvprojectivegeometry.html#ga86b3bbbca7ae731894f90bfd9ebb3a3a" title="Evaluate symmetric epipolar error for a fundamental matrix defined between two images...">symmetricEpipolarDistance</a>(F, matchings[i])));
<a name="l00357"></a>00357                 Q_WARNING(distance &lt; 1e-6);
<a name="l00358"></a>00358                 }
<a name="l00359"></a>00359 
<a name="l00360"></a>00360         <span class="keyword">const</span> <a class="code" href="classQVVector.html" title="Implementation of numerical vectors.">QVVector</a> result2 = symmetricEpipolarDistance2(F, matchings);
<a name="l00361"></a>00361         Q_ASSERT_X(result.count() == matchings.count(), <span class="stringliteral">&quot;symmetricEpipolarDistance()&quot;</span>, <span class="stringliteral">&quot;number of residuals differs from number of matchings&quot;</span>);
<a name="l00362"></a>00362         Q_ASSERT_X(result2.count() == result.count(), <span class="stringliteral">&quot;symmetricEpipolarDistance()&quot;</span>, <span class="stringliteral">&quot;number of estimated residuals differs from number of ground-truth residuals&quot;</span>);
<a name="l00363"></a>00363 
<a name="l00364"></a>00364         <span class="keyword">const</span> <span class="keywordtype">double</span>    max_residuals_norm = MAX(result.norm2(), result2.<a class="code" href="classQVVector.html#a49c6f41f1fa80efcc943f1c26fdcbf05" title="Norm 2 of the vector.">norm2</a>()) / matchings.count(),
<a name="l00365"></a>00365                                         relative_error = (result - result2).norm2() / max_residuals_norm;
<a name="l00366"></a>00366         <span class="comment">//std::cout &lt;&lt; &quot;||r - r||&#39; = &quot; &lt;&lt; relative_error &lt;&lt; &quot;\t&quot; &lt;&lt; result.count() &lt;&lt; &quot;\t&quot; &lt;&lt; result2.count() &lt;&lt; std::endl;</span>
<a name="l00367"></a>00367         <span class="comment">//std::cout &lt;&lt; &quot;max ||r|| , ||r||&#39; = &quot; &lt;&lt; max_residuals_norm &lt;&lt; &quot;\t&quot; &lt;&lt; result.count() &lt;&lt; &quot;\t&quot; &lt;&lt; result2.count() &lt;&lt; std::endl;</span>
<a name="l00368"></a>00368         <span class="comment">/*if(relative_error &gt; 1e-10)</span>
<a name="l00369"></a>00369 <span class="comment">                {</span>
<a name="l00370"></a>00370 <span class="comment">                std::cout &lt;&lt; result &lt;&lt; std::endl;</span>
<a name="l00371"></a>00371 <span class="comment">                std::cout &lt;&lt; result2 &lt;&lt; std::endl;</span>
<a name="l00372"></a>00372 <span class="comment">                std::cout &lt;&lt; (result-result2) &lt;&lt; std::endl;</span>
<a name="l00373"></a>00373 <span class="comment">                }*/</span>
<a name="l00374"></a>00374         Q_WARNING_X( (relative_error &lt; 1e-8) or (max_residuals_norm &lt; 1e-8), <span class="stringliteral">&quot;symmetricEpipolarDistance()&quot;</span>, <span class="stringliteral">&quot;relative error with ground-truth residuals is too high&quot;</span>);
<a name="l00375"></a>00375 <span class="preprocessor">        #endif // DEBUG</span>
<a name="l00376"></a>00376 <span class="preprocessor"></span>
<a name="l00377"></a>00377         <span class="keywordflow">return</span> result;
<a name="l00378"></a>00378         }
<a name="l00379"></a>00379 
<a name="l00380"></a>00380 <span class="comment">// --------------------------------------------------------------------------</span>
<a name="l00381"></a>00381 
<a name="l00382"></a>00382 <span class="keywordtype">bool</span> iterativeLocalOptimization2(<span class="keyword">const</span> QList&lt;QPointFMatching&gt; &amp;matchings,  QList&lt;QPointFMatching&gt; &amp;result, <span class="keyword">const</span> <span class="keywordtype">double</span> maxEE, <span class="keyword">const</span> <span class="keywordtype">int</span> minInliers)
<a name="l00383"></a>00383         {
<a name="l00384"></a>00384         result = matchings;
<a name="l00385"></a>00385 
<a name="l00386"></a>00386         <span class="keywordflow">while</span>(<span class="keyword">true</span>)
<a name="l00387"></a>00387                 {
<a name="l00388"></a>00388                 <span class="comment">//  1) Estimar fundamental &#39;estF&#39;</span>
<a name="l00389"></a>00389                 <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> F = <a class="code" href="group__qvprojectivegeometry.html#ga721c81d3a9e9c7c2e09f5867241c7021" title="Obtains the fundamental matrix between two images using the 8-point algorithm.">computeFundamentalMatrix</a>(result);
<a name="l00390"></a>00390                 <span class="keywordflow">if</span> (F == <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a>())
<a name="l00391"></a>00391                         <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00392"></a>00392 
<a name="l00393"></a>00393                 <span class="comment">//  2) Evaluar error para todas las correspondencias</span>
<a name="l00394"></a>00394                 <span class="keyword">const</span> <a class="code" href="classQVVector.html" title="Implementation of numerical vectors.">QVVector</a> residuals = <a class="code" href="group__qvprojectivegeometry.html#ga86b3bbbca7ae731894f90bfd9ebb3a3a" title="Evaluate symmetric epipolar error for a fundamental matrix defined between two images...">symmetricEpipolarDistance</a>(F, result.toVector());
<a name="l00395"></a>00395 
<a name="l00396"></a>00396                 <span class="comment">//              2.0) Si el error para todas es menor de cierto umbral &#39;maxEE&#39;, parar y devolver fundamental &#39;estF&#39;.</span>
<a name="l00397"></a>00397                 <span class="keyword">const</span> <span class="keywordtype">double</span> actualMax = residuals.<a class="code" href="classQVVector.html#a6695f3c638ef5e1eb50df4d48d6f6a99" title="Maximal value contained in the vector.">max</a>();
<a name="l00398"></a>00398                 <span class="keywordflow">if</span> (actualMax &lt; maxEE)
<a name="l00399"></a>00399                         <span class="keywordflow">return</span> <span class="keyword">true</span>;
<a name="l00400"></a>00400 
<a name="l00401"></a>00401                 <span class="comment">//                      -&gt; si no se han eliminado matchings: FALLO. No se pueden descartar correspondencias con un error demasiado elevado.</span>
<a name="l00402"></a>00402                 <span class="keyword">const</span> <span class="keywordtype">double</span> median = residuals.<a class="code" href="classQVVector.html#aada9281a571f1a7ef99b161af80b38be" title="Median value.">median</a>();
<a name="l00403"></a>00403                 <span class="keywordflow">if</span> (actualMax &lt; 2.0*median)
<a name="l00404"></a>00404                         <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00405"></a>00405 
<a name="l00406"></a>00406                 <span class="comment">//              2.1) Si no, evaluar mediana y filtar correspondencias con error mayor de MAX(2*median, maxEE)</span>
<a name="l00407"></a>00407                 QList&lt;QPointFMatching&gt; newMatchings;
<a name="l00408"></a>00408                 <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i = 0; i &lt; residuals.count(); i++)
<a name="l00409"></a>00409                         <span class="keywordflow">if</span> (residuals[i] &lt; MAX(2*median, maxEE))
<a name="l00410"></a>00410                                 newMatchings &lt;&lt; result[i];
<a name="l00411"></a>00411 
<a name="l00412"></a>00412                 <span class="comment">//                      -&gt; si el número de puntos restante es inferior a cierto umbral: FALLO. Puntos insuficientes para robustez.</span>
<a name="l00413"></a>00413                 <span class="keywordflow">if</span> (newMatchings.count() &lt; minInliers)
<a name="l00414"></a>00414                         <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00415"></a>00415 
<a name="l00416"></a>00416                 <span class="comment">//                      -&gt; en otro caso, repetir punto 1) con nuevos conjunto de puntos filtrados.</span>
<a name="l00417"></a>00417                 result = newMatchings;
<a name="l00418"></a>00418                 }
<a name="l00419"></a>00419 
<a name="l00420"></a>00420         <span class="keywordflow">return</span> <span class="keyword">true</span>;
<a name="l00421"></a>00421         }
<a name="l00422"></a>00422 
<a name="l00423"></a>00423 <span class="keywordtype">bool</span> iterativeLocalOptimization(<span class="keyword">const</span> QList&lt;QPointFMatching&gt; &amp;matchings,  QList&lt;QPointFMatching&gt; &amp;result, <span class="keyword">const</span> <span class="keywordtype">double</span> maxEE, <span class="keyword">const</span> <span class="keywordtype">int</span> minInliers)
<a name="l00424"></a>00424         {
<a name="l00425"></a>00425         result = matchings;
<a name="l00426"></a>00426 
<a name="l00427"></a>00427         <span class="keywordflow">while</span>(<span class="keyword">true</span>)
<a name="l00428"></a>00428                 {
<a name="l00429"></a>00429                 <span class="comment">// Estimate fundamental matrix.</span>
<a name="l00430"></a>00430                 <a class="code" href="classQVMatrix.html" title="Implementation of numerical matrices.">QVMatrix</a> F;
<a name="l00431"></a>00431                 <span class="keywordflow">if</span> (not <a class="code" href="group__qvprojectivegeometry.html#ga721c81d3a9e9c7c2e09f5867241c7021" title="Obtains the fundamental matrix between two images using the 8-point algorithm.">computeFundamentalMatrix</a>(result.toVector(), F))
<a name="l00432"></a>00432                         <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00433"></a>00433 
<a name="l00434"></a>00434                 <span class="comment">// Evaluate symmetric epipolar error for the matchings.</span>
<a name="l00435"></a>00435                 <span class="keyword">const</span> <a class="code" href="classQVVector.html" title="Implementation of numerical vectors.">QVVector</a> residuals = <a class="code" href="group__qvprojectivegeometry.html#ga86b3bbbca7ae731894f90bfd9ebb3a3a" title="Evaluate symmetric epipolar error for a fundamental matrix defined between two images...">symmetricEpipolarDistance</a>(F, result.toVector());
<a name="l00436"></a>00436 
<a name="l00437"></a>00437                 <span class="comment">// If the maximal error is below a threshold value &#39;maxEE&#39;, the algorithm successes and returns the fundamental matrix.</span>
<a name="l00438"></a>00438                 <span class="keyword">const</span> <span class="keywordtype">double</span> actualMax = residuals.<a class="code" href="classQVVector.html#a6695f3c638ef5e1eb50df4d48d6f6a99" title="Maximal value contained in the vector.">max</a>();
<a name="l00439"></a>00439                 <span class="keywordflow">if</span> (actualMax &lt; maxEE)
<a name="l00440"></a>00440                         <span class="keywordflow">return</span> <span class="keyword">true</span>;
<a name="l00441"></a>00441 
<a name="l00442"></a>00442                 <span class="comment">// Evaluate median value of the errors.</span>
<a name="l00443"></a>00443                 <span class="keyword">const</span> <span class="keywordtype">double</span> median = residuals.<a class="code" href="classQVVector.html#aada9281a571f1a7ef99b161af80b38be" title="Median value.">median</a>();
<a name="l00444"></a>00444 
<a name="l00445"></a>00445                 <span class="comment">// If no one of the matchings has an error above two times the median, the algorithm fails.</span>
<a name="l00446"></a>00446                 <span class="comment">// The algorithm will not discard any new matchings, and there are matchings with an error above &#39;maxEE&#39;.</span>
<a name="l00447"></a>00447                 <span class="keywordflow">if</span> (actualMax &lt; 2.0*median)
<a name="l00448"></a>00448                         <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00449"></a>00449 
<a name="l00450"></a>00450                 <span class="comment">// Otherwise, eliminate matchings with an error above a threshold value.</span>
<a name="l00451"></a>00451                 <span class="comment">// This value is the maximal of two times the median and &#39;maxEE&#39;.</span>
<a name="l00452"></a>00452                 QList&lt;QPointFMatching&gt; newMatchings;
<a name="l00453"></a>00453                 <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i = 0; i &lt; residuals.count(); i++)
<a name="l00454"></a>00454                         <span class="keywordflow">if</span> (residuals[i] &lt; MAX(2*median, maxEE))
<a name="l00455"></a>00455                                 newMatchings &lt;&lt; result[i];
<a name="l00456"></a>00456 
<a name="l00457"></a>00457                 <span class="comment">// If there are not enough remaining matchings, return fail.</span>
<a name="l00458"></a>00458                 <span class="keywordflow">if</span> (newMatchings.count() &lt; minInliers)
<a name="l00459"></a>00459                         <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00460"></a>00460 
<a name="l00461"></a>00461                 <span class="comment">// Otherwise start again the filtering process.</span>
<a name="l00462"></a>00462                 result = newMatchings;
<a name="l00463"></a>00463                 }
<a name="l00464"></a>00464 
<a name="l00465"></a>00465         <span class="keywordflow">return</span> <span class="keyword">true</span>;
<a name="l00466"></a>00466         }
<a name="l00467"></a>00467 
</pre></div></div>
</td></tr></table>

<br /><hr><br />
<center><a href="http://perception.inf.um.es/QVision">QVision framework</a>.
<a href="http://perception.inf.um.es">PARP research group</a>.
Copyright &copy; 2007, 2008, 2009, 2010, 2011.</center>
<br />
</body>
</html>
